Skip to main content

pacenotes_installer\engine\execute/
run.rs

1/// What a run did, for the summary.
2#[derive(Clone, Debug, Default, PartialEq, Eq)]
3pub struct Outcome {
4    pub installed: Vec<String>,
5    pub uninstalled: Vec<String>,
6    /// Kept rather than deleted, because they could not be put back or were
7    /// changed by someone else after we wrote them.
8    pub left_alone: Vec<String>,
9    /// `None` when the plan had nothing to do.
10    pub restore_point: Option<String>,
11}
12
13/// What every step of one run works on.
14pub struct RunContext<'a> {
15    pub game_dir: &'a std::path::Path,
16    pub cache: &'a crate::cache::Cache,
17    pub ledger: &'a mut crate::ledger::Ledger,
18    pub watcher: &'a mut dyn crate::engine::Watcher,
19}
20
21/// Carries out `plan` with what `preflight` prepared for it.
22pub fn execute(
23    plan: &crate::engine::Plan,
24    prepared: &crate::engine::Preflight,
25    game_dir: &std::path::Path,
26    cache: &crate::cache::Cache,
27    ledger: &mut crate::ledger::Ledger,
28    watcher: &mut dyn crate::engine::Watcher,
29) -> Result<Outcome, super::ExecuteError> {
30    let mut outcome = Outcome::default();
31    if plan.is_empty() {
32        return Ok(outcome);
33    }
34    let point = super::restore_point::open_restore_point(game_dir, ledger, watcher)?;
35    outcome.restore_point = Some(point.clone());
36    let mut run = RunContext {
37        game_dir,
38        cache,
39        ledger,
40        watcher,
41    };
42
43    let uninstalls = plan.uninstalls();
44    for (index, key) in uninstalls.iter().enumerate() {
45        let count = uninstalls.len() as u64;
46        run.watcher
47            .phase(crate::engine::Phase::Uninstalling, key, index as u64, count);
48        super::uninstall_package::uninstall_package(&mut run, key, &mut outcome)?;
49    }
50
51    let mut progress = super::install_package::Progress {
52        written: 0,
53        total: prepared.install_bytes,
54    };
55    for key in plan.installs() {
56        let files = prepared.files.get(key).map_or(&[][..], Vec::as_slice);
57        // The version the user just chose, which is the one the cache index holds.
58        let cached =
59            run.cache.get(key).cloned().ok_or_else(|| {
60                super::ExecuteError::extract(key, "it is not in the download cache")
61            })?;
62        let what = super::install_package::Installing {
63            key,
64            sha256: &cached.sha256,
65            version: &cached.version,
66            exclusive_group: cached.exclusive_group.as_deref(),
67        };
68        super::install_package::install_package(&mut run, &what, files, &point, &mut progress)?;
69        outcome.installed.push(key.to_string());
70    }
71    Ok(outcome)
72}